#ifndef GLOBAL_H
#define GLOBAL_H

#include "smpp/parameters/smpp_prameters_header.h"
#include "smpp/parameters/smpp_prameters_mandatory.h"
#include "smpp/sessions/smpp_client_async_session.h"
#include "smpp/sessions/smpp_server_async_session.h"
#include "qtjsonsettings/qtjsonsettings.h"
#include "logmanager/log_global.h"
#include "logencoder/log_encoder.h"
#include "logparams/log_message_codes.h"
#include "logparams/log_message_parameters.h"
#include "logparams/log_app.h"
#include "logparams/log_class.h"
#include "logparams/log_obj.h"
#include "dbmanager/database_manager.h"
#include "binaryrpc/binaryrpc_client.h"
#include "binaryrpc/binaryrpc_server.h"
#include "binaryrpc/binaryrpc_encoder.h"
#include "binaryrpc/binaryrpc_helper.h"
#include <QtCore/QDateTime>
#include <QtCore/QRegExp>

#ifdef Q_OS_UNIX
static const char LOG_FILE_PATH[]       = "/var/log";
static const char PID_FILE[]            = "/var/run/smsrouter.pid";
static const char DEFAULT_CONFIG_PATH[] =
  "/usr/local/etc/smsrouter/config.json";
#else
static const char LOG_FILE_PATH[]       = "./";
static const char DEFAULT_CONFIG_PATH[] = "config.json";
#endif
static const char APP_NAME[]            = "smsrouter";
static const char APP_VERSION[]         = "1.0.0";
static const QString APP_NAME_VERSION   =
  QString("%1 %2").arg(APP_NAME).arg(APP_VERSION);
static const char HELP[]                =
"  [OPTION]...\n"
"Options:\n"
"    -help | -h       Display this help\n"
"    -version | -v    Display program version\n"
"    -config <path>   Override the default path where user config are stored";

static const char HELP_OPTION1[]        = "-h";
static const char HELP_OPTION2[]        = "-help";
static const char VERSION_OPTION1[]     = "-v";
static const char VERSION_OPTION2[]     = "-version";
static const char CONFIG_OPTION[]       = "-config";

static const char UNIX_DAEMON_CLS[]     = "UnixDaemon";

static const char KERNEL_CLS[]          = "Kernel";

static const char SESSION_MANAGER_CLS[] = "SessionManager";

static const char MAILER_CLS[]          = "Mailer";

static const char SRC_DELIVER_H_CLS[]   = "SrcDeliverHandler";

static const char SRC_SUBMIT_H_CLS[]    = "SrcSubmitHandler";

static const char DEST_DELIVER_H_CLS[]  = "DestDeliverHandler";

static const char DEST_SUBMIT_H_CLS[]   = "DestSubmitHandler";

static const char KERNEL_KEY[]          = "kernel";
static const char DIRECTIONS_KEY[]      = "directions";
static const char MESSAGES_KEY[]        = "messages";
static const char SESSION_MANAGER_KEY[] = "session_manager";
static const char MAILER_KEY[]          = "mailer";
static const char LOG_LEVEL_KEY[]       = "log_level";
static const char KERNEL_ID_KEY[]       = "kernel_id";
static const char DB_HOST_KEY[]         = "db_host";
static const char DB_PORT_KEY[]         = "db_port";
static const char DB_NAME_KEY[]         = "db_name";
static const char DB_UNAME_KEY[]        = "db_uname";
static const char DB_PASS_KEY[]         = "db_pass";
static const char NUM_CONNECT_DB[]      = "num_connect_db";
static const char EXEC_QUERY_TIMEOUT[]  = "exec_query_timeout";

namespace smsrouter {

  enum State {
    STARTED,
    STARTING,
    ERROR,
    STOPING,
    STOPED
  };

  class SrcSubmitSm {
  public:
    SrcSubmitSm(quint32 src_session_id,
                quint32 src_message_id,
                const smpp::pdu::SubmitSm &p) :
      receive_date(QDateTime::currentMSecsSinceEpoch()),
      src_session_id(src_session_id),
      dest_session_id(0),
      src_addr_ton_after(p.getSourceAddrTon()),
      src_addr_npi_after(p.getSourceAddrNpi()),
      src_addr_after(p.getSourceAddr()),
      sm(p),
      src_message_id(src_message_id),
      message_state(smpp::parameters::message_state::ENROUTE),
      error_code(smpp::parameters::command_status::ESME_ROK) {

    }

    quint64 receive_date;
    quint32 src_session_id;
    quint32 dest_session_id;
    quint8 src_addr_ton_after;
    quint8 src_addr_npi_after;
    QString src_addr_after;
    smpp::pdu::SubmitSm sm;
    quint32 src_message_id;
    quint8 message_state;
    quint32 error_code;
  };

  class SrcDeliverSm {
  public:
    SrcDeliverSm(quint32 src_session_id,
                 quint64 receive_date,
                 quint32 src_message_id,
                 const smpp::pdu::DeliverSm &dm,
                 quint8 attempt) :
      receive_date(receive_date),
      src_session_id(src_session_id),
      dm(dm),
      src_message_id(src_message_id),
      error_code(smpp::parameters::command_status::ESME_ROK),
      attempt(attempt) {

    }

    quint64 receive_date;
    quint32 src_session_id;
    smpp::pdu::DeliverSm dm;
    quint32 src_message_id;
    quint32 error_code;
    quint8 attempt;
  };

  class DestSubmitSm {
  public:
    DestSubmitSm(quint32 src_session_id,
                 quint32 dest_session_id,
                 quint64 receive_date,
                 quint32 src_message_id,
                 quint8 src_addr_ton_before,
                 quint8 src_addr_npi_before,
                 const QString &src_addr_before,
                 const smpp::pdu::SubmitSm &p,
                 quint8 attempt) :
      src_message_id(src_message_id),
      dest_message_id(0),
      src_session_id(src_session_id),
      dest_session_id(dest_session_id),
      receive_date(receive_date),
      src_addr_ton_before(src_addr_ton_before),
      src_addr_npi_before(src_addr_npi_before),
      src_addr_before(src_addr_before),
      sm(p),
      error_code(smpp::parameters::command_status::ESME_ROK),
      attempt(attempt) {

    }
    quint32 src_message_id;
    quint32 dest_message_id;
    quint32 src_session_id;
    quint32 dest_session_id;
    quint64 receive_date;
    quint8 src_addr_ton_before;
    quint8 src_addr_npi_before;
    QString src_addr_before;
    smpp::pdu::SubmitSm sm;
    quint32 error_code;
    quint8 attempt;
  };

  class DestDeliverSm {
  public:
    DestDeliverSm(quint32 dest_session_id,
                  quint32 dest_message_id,
                  quint32 error_code,
                  quint8 message_state,
                  const smpp::pdu::DeliverSm &dm) :
      receive_date(QDateTime::currentMSecsSinceEpoch()),
      alt_dest_session_id(0),
      src_session_id(0),
      dest_session_id(dest_session_id),
      dest_message_id(dest_message_id),
      error_code(error_code),
      message_state(message_state),
      dm(dm) {

    }

    qint64 receive_date;
    quint32 alt_dest_session_id;
    quint32 src_session_id;
    quint32 dest_session_id;
    quint32 dest_message_id;
    quint32 error_code;
    quint8 message_state;
    smpp::pdu::DeliverSm dm;
  };

  enum MessageIdCode {
    NUM,
    HEX
  };

  enum BindTypes {
    TX,
    RX,
    TRX
  };

  enum RowState {
    NO_UPDATED,
    UPDATED,
    DELETED,
    ADDED
  };

  class KernelSettings {
  public:
    KernelSettings(quint32 id,
                   const QHostAddress &rpc_ip,
                   quint16 rpc_port,
                   const QHostAddress &smpp_ip,
                   quint16 smpp_port,
                   int def_max_in_speed,
                   int def_max_out_speed,
                   int def_session_init_time,
                   int def_enquire_link_time,
                   int def_inactivity_time,
                   int def_transaction_time,
                   int def_max_in_trans,
                   int def_max_out_trans,
                   const QString &name,
                   quint32 last_message_id,
                   const QHostAddress &billing_ip,
                   quint16 billing_port,
                   RowState state = ADDED) :
      id(id),
      rpc_ip(rpc_ip),
      rpc_port(rpc_port),
      smpp_ip(smpp_ip),
      smpp_port(smpp_port),
      def_max_in_speed(def_max_in_speed),
      def_max_out_speed(def_max_out_speed),
      def_session_init_time(def_session_init_time),
      def_enquire_link_time(def_enquire_link_time),
      def_inactivity_time(def_inactivity_time),
      def_transaction_time(def_transaction_time),
      def_max_in_trans(def_max_in_trans),
      def_max_out_trans(def_max_out_trans),
      name(name),
      last_message_id(last_message_id),
      billing_ip(billing_ip),
      billing_port(billing_port),
      state(state) {

    }

    quint32 id;
    QHostAddress rpc_ip;
    quint16 rpc_port;
    QHostAddress smpp_ip;
    quint16 smpp_port;
    int def_max_in_speed;
    int def_max_out_speed;
    int def_session_init_time;
    int def_enquire_link_time;
    int def_inactivity_time;
    int def_transaction_time;
    int def_max_in_trans;
    int def_max_out_trans;
    QString name;
    quint32 last_message_id;
    QHostAddress billing_ip;
    quint16 billing_port;
    RowState state;
  };

  class DeliveryProfilesRecord {
  public:
    DeliveryProfilesRecord(quint32 id,
                           const QString &name,
                           RowState state = ADDED) :
      id(id),
      name(name),
      state(state) {

    }

    quint32 id;
    QString name;
    RowState state;
  };

  class DeliveryErrorCodesRecord {
  public:
    DeliveryErrorCodesRecord(quint32 id,
                             quint32 delivery_profile_id,
                             quint32 error_code,
                             const QString &description,
                             int timeout,
                             RowState state = ADDED) :
      id(id),
      delivery_profile_id(delivery_profile_id),
      error_code(error_code),
      description(description),
      timeout(timeout),
      state(state) {

    }

    quint32 id;
    quint32 delivery_profile_id;
    quint32 error_code;
    QString description;
    int timeout;
    RowState state;
  };

  class RouteTableRecord {
  public:
    RouteTableRecord(quint32 id,
                     quint32 src_session_id,
                     quint32 dest_session_id,
                     const QRegExp &src_addr,
                     const QRegExp &dest_addr,
                     quint16 metric,
                     RowState state = ADDED) :
      id(id),
      src_session_id(src_session_id),
      dest_session_id(dest_session_id),
      src_addr(src_addr),
      dest_addr(dest_addr),
      metric(metric),
      state(state) {

    }

    quint32 id;
    quint32 src_session_id;
    quint32 dest_session_id;
    QRegExp src_addr;
    QRegExp dest_addr;
    quint16 metric;
    RowState state;
  };

  class PoolTranslatorRecord {
  public:
    PoolTranslatorRecord(quint32 id,
                         quint64 begin_addr,
                         quint64 end_addr,
                         RowState state = ADDED) :
      id(id),
      begin_addr(begin_addr),
      end_addr(end_addr),
      state(state) {

    }

    quint32 id;
    quint64 begin_addr;
    quint64 end_addr;
    RowState state;
  };

  class SrcTranslatorRecord {
  public:
    SrcTranslatorRecord(quint32 id,
                        quint32 src_session_id,
                        quint32 dest_session_id,
                        const QRegExp &src_addr,
                        const QRegExp &dest_addr,
                        const QString &src_addr_after,
                        quint8 src_ton_after,
                        quint8 src_npi_after,
                        quint32 pool_id = 0,
                        RowState state = ADDED) :
      id(id),
      src_session_id(src_session_id),
      dest_session_id(dest_session_id),
      src_addr(src_addr),
      dest_addr(dest_addr),
      src_addr_after(src_addr_after),
      src_ton_after(src_ton_after),
      src_npi_after(src_npi_after),
      pool_id(pool_id),
      state(state) {

    }

    quint32 id;
    quint32 src_session_id;
    quint32 dest_session_id;
    QRegExp src_addr;
    QRegExp dest_addr;
    QString src_addr_after;
    quint8 src_ton_after;
    quint8 src_npi_after;
    quint32 pool_id;
    RowState state;
  };

  class SrcSessionSettings {
  public:
    SrcSessionSettings(quint32 id,
                       const QString &name,
                       int max_in_speed,
                       int max_out_speed,
                       int session_init_time,
                       int enquire_link_time,
                       int inactivity_time,
                       int transaction_time,
                       int max_in_trans,
                       int max_out_trans,
                       quint8 bind_type,
                       const QString &system_id,
                       const QString &password,
                       quint32 billing_resource_id,
                       bool pay_only_delivered,
                       const QRegExp &src_white_list,
                       const QRegExp &src_black_list,
                       const QRegExp &dest_white_list,
                       const QRegExp &dest_black_list,
                       quint32 delivery_profile_id,
                       quint8 delivery_attempts,
                       RowState state = ADDED) :
      id(id),
      name(name),
      max_in_speed(max_in_speed),
      max_out_speed(max_out_speed),
      session_init_time(session_init_time),
      enquire_link_time(enquire_link_time),
      inactivity_time(inactivity_time),
      transaction_time(transaction_time),
      max_in_trans(max_in_trans),
      max_out_trans(max_out_trans),
      bind_type(bind_type),
      system_id(system_id),
      password(password),
      billing_resource_id(billing_resource_id),
      pay_only_delivered(pay_only_delivered),
      src_white_list(src_white_list),
      src_black_list(src_black_list),
      dest_white_list(dest_white_list),
      dest_black_list(dest_black_list),
      delivery_profile_id(delivery_profile_id),
      delivery_attempts(delivery_attempts),
      state(state) {

    }

    quint32 id;
    QString name;
    int max_in_speed;
    int max_out_speed;
    int session_init_time;
    int enquire_link_time;
    int inactivity_time;
    int transaction_time;
    int max_in_trans;
    int max_out_trans;
    quint8 bind_type;
    QString system_id;
    QString password;
    quint32 billing_resource_id;
    bool pay_only_delivered;
    QRegExp src_white_list;
    QRegExp src_black_list;
    QRegExp dest_white_list;
    QRegExp dest_black_list;
    quint32 delivery_profile_id;
    quint8 delivery_attempts;
    RowState state;
  };

  class DestSessionSettings {
  public:
    DestSessionSettings(quint32 id,
                        const QString &name,
                        const QHostAddress &ip,
                        quint16 port,
                        int max_in_speed,
                        int max_out_speed,
                        int session_init_time,
                        int enquire_link_time,
                        int inactivity_time,
                        int transaction_time,
                        int max_in_trans,
                        int max_out_trans,
                        const QString &system_id,
                        const QString &password,
                        const QString &system_type,
                        const QRegExp &error_code_rule,
                        const QRegExp &message_id_rule,
                        const QRegExp &status_rule,
                        MessageIdCode deliver_message_id,
                        MessageIdCode submit_message_id,
                        int recovery_time,
                        quint32 billing_resource_id,
                        bool pay_only_delivered,
                        const QRegExp &src_white_list,
                        const QRegExp &src_black_list,
                        const QRegExp &dest_white_list,
                        const QRegExp &dest_black_list,
                        quint32 delivery_profile_id,
                        quint8 delivery_attempts,
                        RowState state = ADDED) :
      id(id),
      name(name),
      ip(ip),
      port(port),
      max_in_speed(max_in_speed),
      max_out_speed(max_out_speed),
      session_init_time(session_init_time),
      enquire_link_time(enquire_link_time),
      inactivity_time(inactivity_time),
      transaction_time(transaction_time),
      max_in_trans(max_in_trans),
      max_out_trans(max_out_trans),
      system_id(system_id),
      password(password),
      system_type(system_type),
      error_code_rule(error_code_rule),
      message_id_rule(message_id_rule),
      status_rule(status_rule),
      deliver_message_id(deliver_message_id),
      submit_message_id(submit_message_id),
      recovery_time(recovery_time),
      billing_resource_id(billing_resource_id),
      pay_only_delivered(pay_only_delivered),
      src_white_list(src_white_list),
      src_black_list(src_black_list),
      dest_white_list(dest_white_list),
      dest_black_list(dest_black_list),
      delivery_profile_id(delivery_profile_id),
      delivery_attempts(delivery_attempts),
      state(state) {

    }

    quint32 id;
    QString name;
    QHostAddress ip;
    quint16 port;
    int max_in_speed;
    int max_out_speed;
    int session_init_time;
    int enquire_link_time;
    int inactivity_time;
    int transaction_time;
    int max_in_trans;
    int max_out_trans;
    QString system_id;
    QString password;
    QString system_type;
    QRegExp error_code_rule;
    QRegExp message_id_rule;
    QRegExp status_rule;
    MessageIdCode deliver_message_id;
    MessageIdCode submit_message_id;
    int recovery_time;
    quint32 billing_resource_id;
    bool pay_only_delivered;
    QRegExp src_white_list;
    QRegExp src_black_list;
    QRegExp dest_white_list;
    QRegExp dest_black_list;
    quint32 delivery_profile_id;
    quint8 delivery_attempts;
    RowState state;
  };

} // namespace smsrouter

#endif // GLOBAL_H
